#include "logger.h"
#include <iostream>
#include <cstdarg>
#include <algorithm>

// 添加filesystem支持
#if __cplusplus >= 201703L && __has_include(<filesystem>)
    #include <filesystem>
    namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
    #include <experimental/filesystem>
    namespace fs = std::experimental::filesystem;
#else
    // 如果没有filesystem支持，使用传统方法
    #include <sys/stat.h>
    #include <unistd.h>
#endif

namespace yquote {

// ConsoleSink 实现
ConsoleSink::ConsoleSink(bool use_colors) : use_colors_(use_colors) {}

void ConsoleSink::write(const LogMessage& msg) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    std::string color_code = use_colors_ ? getColorCode(msg.level) : "";
    std::string reset_code = use_colors_ ? getResetCode() : "";
    
    auto& stream = (msg.level >= LogLevel::ERROR) ? std::cerr : std::cout;
    
    // 格式化时间戳
    auto time_t = std::chrono::system_clock::to_time_t(msg.timestamp);
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        msg.timestamp.time_since_epoch()) % 1000;
    
    stream << color_code 
           << "[" << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S")
           << "." << std::setfill('0') << std::setw(3) << ms.count() << "] "
           << "[" << getLevelString(msg.level) << "] "
           << msg.message
           << reset_code << std::endl;
}

void ConsoleSink::flush() {
    std::cout.flush();
    std::cerr.flush();
}

std::string ConsoleSink::getColorCode(LogLevel level) const {
    switch (level) {
        case LogLevel::TRACE: return "\033[37m";    // 白色
        case LogLevel::DEBUG: return "\033[36m";    // 青色
        case LogLevel::INFO:  return "\033[32m";    // 绿色
        case LogLevel::WARN:  return "\033[33m";    // 黄色
        case LogLevel::ERROR: return "\033[31m";    // 红色
        case LogLevel::FATAL: return "\033[35m";    // 紫色
        default: return "";
    }
}

std::string ConsoleSink::getResetCode() const {
    return "\033[0m";
}

std::string ConsoleSink::getLevelString(LogLevel level) const {
    switch (level) {
        case LogLevel::TRACE: return "TRACE";
        case LogLevel::DEBUG: return "DEBUG";
        case LogLevel::INFO:  return "INFO ";
        case LogLevel::WARN:  return "WARN ";
        case LogLevel::ERROR: return "ERROR";
        case LogLevel::FATAL: return "FATAL";
        default: return "UNKNOWN";
    }
}

// FileSink 实现
FileSink::FileSink(const std::string& filename, bool append) {
    auto mode = append ? std::ios::app : std::ios::trunc;
    file_.open(filename, std::ios::out | mode);
    if (!file_.is_open()) {
        throw std::runtime_error("无法打开日志文件: " + filename);
    }
}

FileSink::~FileSink() {
    if (file_.is_open()) {
        file_.close();
    }
}

void FileSink::write(const LogMessage& msg) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    if (!file_.is_open()) return;
    
    // 格式化时间戳
    auto time_t = std::chrono::system_clock::to_time_t(msg.timestamp);
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        msg.timestamp.time_since_epoch()) % 1000;
    
    file_ << "[" << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S")
          << "." << std::setfill('0') << std::setw(3) << ms.count() << "] "
          << "[" << getLevelString(msg.level) << "] "
          << "[" << msg.thread_id << "] "
          << msg.message
          << " (" << msg.file << ":" << msg.line << ")" << std::endl;
}

void FileSink::flush() {
    std::lock_guard<std::mutex> lock(mutex_);
    if (file_.is_open()) {
        file_.flush();
    }
}

std::string FileSink::getLevelString(LogLevel level) const {
    switch (level) {
        case LogLevel::TRACE: return "TRACE";
        case LogLevel::DEBUG: return "DEBUG";
        case LogLevel::INFO:  return "INFO ";
        case LogLevel::WARN:  return "WARN ";
        case LogLevel::ERROR: return "ERROR";
        case LogLevel::FATAL: return "FATAL";
        default: return "UNKNOWN";
    }
}

// RotatingFileSink 实现
RotatingFileSink::RotatingFileSink(const std::string& base_filename, size_t max_size, size_t max_files)
    : base_filename_(base_filename), max_size_(max_size), max_files_(max_files), current_size_(0) {
    
    std::string filename = getCurrentFilename();
    file_.open(filename, std::ios::out | std::ios::app);
    if (!file_.is_open()) {
        throw std::runtime_error("无法打开日志文件: " + filename);
    }
    
    // 获取当前文件大小
    file_.seekp(0, std::ios::end);
    current_size_ = file_.tellp();
}

RotatingFileSink::~RotatingFileSink() {
    if (file_.is_open()) {
        file_.close();
    }
}

void RotatingFileSink::write(const LogMessage& msg) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    if (!file_.is_open()) return;
    
    // 格式化消息
    auto time_t = std::chrono::system_clock::to_time_t(msg.timestamp);
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        msg.timestamp.time_since_epoch()) % 1000;
    
    std::ostringstream oss;
    oss << "[" << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S")
        << "." << std::setfill('0') << std::setw(3) << ms.count() << "] "
        << "[" << getLevelString(msg.level) << "] "
        << "[" << msg.thread_id << "] "
        << msg.message
        << " (" << msg.file << ":" << msg.line << ")" << std::endl;
    
    std::string formatted = oss.str();
    
    // 检查是否需要滚动
    if (current_size_ + formatted.size() > max_size_) {
        rotateFile();
    }
    
    file_ << formatted;
    current_size_ += formatted.size();
}

void RotatingFileSink::flush() {
    std::lock_guard<std::mutex> lock(mutex_);
    if (file_.is_open()) {
        file_.flush();
    }
}

void RotatingFileSink::rotateFile() {
    if (file_.is_open()) {
        file_.close();
    }
    
    // 移动现有文件
    for (size_t i = max_files_ - 1; i > 0; --i) {
        std::string old_name = base_filename_ + "." + std::to_string(i);
        std::string new_name = base_filename_ + "." + std::to_string(i + 1);
        
#if __cplusplus >= 201703L && __has_include(<filesystem>)
        if (fs::exists(old_name)) {
            if (i == max_files_ - 1) {
                fs::remove(new_name); // 删除最老的文件
            }
            fs::rename(old_name, new_name);
        }
#else
        // 使用传统方法检查文件存在性
        struct stat buffer;
        if (stat(old_name.c_str(), &buffer) == 0) {
            if (i == max_files_ - 1) {
                unlink(new_name.c_str()); // 删除最老的文件
            }
            rename(old_name.c_str(), new_name.c_str());
        }
#endif
    }
    
    // 移动当前文件
    std::string current_name = getCurrentFilename();
    std::string backup_name = base_filename_ + ".1";
    
#if __cplusplus >= 201703L && __has_include(<filesystem>)
    if (fs::exists(current_name)) {
        fs::rename(current_name, backup_name);
    }
#else
    struct stat buffer;
    if (stat(current_name.c_str(), &buffer) == 0) {
        rename(current_name.c_str(), backup_name.c_str());
    }
#endif
    
    // 创建新文件
    file_.open(current_name, std::ios::out | std::ios::trunc);
    current_size_ = 0;
}

std::string RotatingFileSink::getCurrentFilename() const {
    return base_filename_;
}

std::string RotatingFileSink::getLevelString(LogLevel level) const {
    switch (level) {
        case LogLevel::TRACE: return "TRACE";
        case LogLevel::DEBUG: return "DEBUG";
        case LogLevel::INFO:  return "INFO ";
        case LogLevel::WARN:  return "WARN ";
        case LogLevel::ERROR: return "ERROR";
        case LogLevel::FATAL: return "FATAL";
        default: return "UNKNOWN";
    }
}

// CallbackSink 实现
CallbackSink::CallbackSink(Callback callback) : callback_(std::move(callback)) {}

void CallbackSink::write(const LogMessage& msg) {
    std::lock_guard<std::mutex> lock(mutex_);
    if (callback_) {
        callback_(msg);
    }
}

// DefaultFormatter 实现
DefaultFormatter::DefaultFormatter(const std::string& pattern) : pattern_(pattern) {}

std::string DefaultFormatter::format(const LogMessage& msg) {
    std::string result = pattern_;
    
    // 替换时间戳
    auto time_t = std::chrono::system_clock::to_time_t(msg.timestamp);
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        msg.timestamp.time_since_epoch()) % 1000;
    
    std::ostringstream time_oss;
    time_oss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S")
             << "." << std::setfill('0') << std::setw(3) << ms.count();
    
    // 简单的字符串替换
    size_t pos = 0;
    while ((pos = result.find("%Y-%m-%d %H:%M:%S.%f", pos)) != std::string::npos) {
        result.replace(pos, 20, time_oss.str());
        pos += time_oss.str().length();
    }
    
    // 替换日志级别
    pos = 0;
    while ((pos = result.find("%l", pos)) != std::string::npos) {
        result.replace(pos, 2, getLevelString(msg.level));
        pos += getLevelString(msg.level).length();
    }
    
    // 替换线程ID
    pos = 0;
    while ((pos = result.find("%t", pos)) != std::string::npos) {
        result.replace(pos, 2, getThreadIdString(msg.thread_id));
        pos += getThreadIdString(msg.thread_id).length();
    }
    
    // 替换消息
    pos = 0;
    while ((pos = result.find("%v", pos)) != std::string::npos) {
        result.replace(pos, 2, msg.message);
        pos += msg.message.length();
    }
    
    // 替换文件名
    pos = 0;
    while ((pos = result.find("%s", pos)) != std::string::npos) {
        result.replace(pos, 2, msg.file);
        pos += msg.file.length();
    }
    
    // 替换行号
    pos = 0;
    while ((pos = result.find("%#", pos)) != std::string::npos) {
        std::string line_str = std::to_string(msg.line);
        result.replace(pos, 2, line_str);
        pos += line_str.length();
    }
    
    return result;
}

std::string DefaultFormatter::getLevelString(LogLevel level) const {
    switch (level) {
        case LogLevel::TRACE: return "TRACE";
        case LogLevel::DEBUG: return "DEBUG";
        case LogLevel::INFO:  return "INFO ";
        case LogLevel::WARN:  return "WARN ";
        case LogLevel::ERROR: return "ERROR";
        case LogLevel::FATAL: return "FATAL";
        default: return "UNKNOWN";
    }
}

std::string DefaultFormatter::getThreadIdString(std::thread::id id) const {
    std::ostringstream oss;
    oss << id;
    return oss.str();
}

// AsyncLogger 实现
AsyncLogger::AsyncLogger() : running_(false) {}

AsyncLogger::~AsyncLogger() {
    stop();
}

void AsyncLogger::start() {
    if (running_.load()) return;
    
    running_.store(true);
    worker_thread_ = std::thread(&AsyncLogger::workerLoop, this);
}

void AsyncLogger::stop() {
    if (!running_.load()) return;
    
    running_.store(false);
    condition_.notify_all();
    
    if (worker_thread_.joinable()) {
        worker_thread_.join();
    }
}

void AsyncLogger::enqueue(LogMessage&& msg) {
    {
        std::lock_guard<std::mutex> lock(queue_mutex_);
        queue_.push(std::move(msg));
    }
    condition_.notify_one();
}

void AsyncLogger::workerLoop() {
    while (running_.load()) {
        std::unique_lock<std::mutex> lock(queue_mutex_);
        condition_.wait(lock, [this] { return !queue_.empty() || !running_.load(); });
        
        while (!queue_.empty()) {
            LogMessage msg = std::move(queue_.front());
            queue_.pop();
            lock.unlock();
            
            // 处理消息（这里需要访问Logger的sinks，需要重新设计）
            // 暂时留空，实际实现中需要回调到Logger
            
            lock.lock();
        }
    }
}

// Logger 实现
Logger& Logger::getInstance() {
    static Logger instance;
    return instance;
}

Logger::~Logger() {
    if (async_logger_) {
        async_logger_->stop();
    }
}

void Logger::setLevel(LogLevel level) {
    std::lock_guard<std::mutex> lock(mutex_);
    level_ = level;
}

LogLevel Logger::getLevel() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return level_;
}

void Logger::addSink(std::shared_ptr<LogSink> sink) {
    std::lock_guard<std::mutex> lock(mutex_);
    sinks_.push_back(sink);
}

void Logger::removeSink(std::shared_ptr<LogSink> sink) {
    std::lock_guard<std::mutex> lock(mutex_);
    auto it = std::find(sinks_.begin(), sinks_.end(), sink);
    if (it != sinks_.end()) {
        sinks_.erase(it);
    }
}

void Logger::clearSinks() {
    std::lock_guard<std::mutex> lock(mutex_);
    sinks_.clear();
}

void Logger::setFormatter(std::shared_ptr<LogFormatter> formatter) {
    std::lock_guard<std::mutex> lock(mutex_);
    formatter_ = formatter;
}

void Logger::setAsync(bool async) {
    std::lock_guard<std::mutex> lock(mutex_);
    async_mode_ = async;
    
    if (async && !async_logger_) {
        async_logger_ = std::make_unique<AsyncLogger>();
        async_logger_->start();
    } else if (!async && async_logger_) {
        async_logger_->stop();
        async_logger_.reset();
    }
}

void Logger::log(LogLevel level, const std::string& message, 
                 const std::string& file, int line, const std::string& function) {
    if (level < level_) return;
    
    LogMessage msg(level, message, file, line, function);
    
    if (async_mode_ && async_logger_) {
        async_logger_->enqueue(std::move(msg));
    } else {
        writeToSinks(msg);
    }
}

void Logger::trace(const std::string& message, const std::string& file, int line, const std::string& function) {
    log(LogLevel::TRACE, message, file, line, function);
}

void Logger::debug(const std::string& message, const std::string& file, int line, const std::string& function) {
    log(LogLevel::DEBUG, message, file, line, function);
}

void Logger::info(const std::string& message, const std::string& file, int line, const std::string& function) {
    log(LogLevel::INFO, message, file, line, function);
}

void Logger::warn(const std::string& message, const std::string& file, int line, const std::string& function) {
    log(LogLevel::WARN, message, file, line, function);
}

void Logger::error(const std::string& message, const std::string& file, int line, const std::string& function) {
    log(LogLevel::ERROR, message, file, line, function);
}

void Logger::fatal(const std::string& message, const std::string& file, int line, const std::string& function) {
    log(LogLevel::FATAL, message, file, line, function);
}

void Logger::flush() {
    std::lock_guard<std::mutex> lock(mutex_);
    for (auto& sink : sinks_) {
        sink->flush();
    }
}

void Logger::writeToSinks(const LogMessage& msg) {
    std::lock_guard<std::mutex> lock(mutex_);
    for (auto& sink : sinks_) {
        sink->write(msg);
    }
}

std::string Logger::formatMessage(const std::string& format, ...) const {
    va_list args;
    va_start(args, format);
    
    // 获取所需的缓冲区大小
    int size = vsnprintf(nullptr, 0, format.c_str(), args);
    va_end(args);
    
    if (size <= 0) return format;
    
    // 分配缓冲区并格式化
    std::vector<char> buffer(size + 1);
    va_start(args, format);
    vsnprintf(buffer.data(), buffer.size(), format.c_str(), args);
    va_end(args);
    
    return std::string(buffer.data());
}

} // namespace yquote 